<?php

class Public_PostsModel extends BlogPublicBaseModel
{
    /**
     * Get post "coordinates"
     *
     * @param Post $post
     * @return array Associative array of strings, keys are strings too: day, month, year and shortcut.
     */
    public function getPostCoordinates(Post $post)
    {
        $result = array();
        $result['shortcut'] = $post->shortcut;
        
        /* @var $date DateTime */
        $date = date_create($post->post_time);
        $result['day'] = $date->format('d');
        $result['month'] = $date->format('m');
        $result['year'] = $date->format('Y');
        
        return $result;
    }
    
	/**
	 * Retrieve blog posts
	 * 
	 * @param boolean $filter If TRUE then hidden posts must be excluded from the results 
	 * @return array Empty array if there are no posts those match given criteria
	 */
	public function findBlogPosts($filter=FALSE)
	{
	    /* @var $us BlogUser */
	    $us = $this->getContext()->getUser();

        $query = Doctrine_Query::create()
            ->from('Post p')
            ->orderBy('p.post_time DESC');

	    if (!$us->hasCredential('posts.view_hidden') || $filter===TRUE) {
	        // exclude hidden posts
            $query->andWhere('is_published = ?', true);
	    }
        $result = $query->execute();
        return $result;
	}
	
	/**
	 * Retrieve all blog posts marked with tag
	 *
	 * @param string $tag_name
	 * @param boolean $filter
	 * @return Doctrine_Collection
	 */
	public function findBlogPostsByTag($tag_name, $filter=FALSE)
	{
	    $us = $this->getContext()->getUser();

        $query = Doctrine_Query::create()
            ->from('Post p')
            ->innerJoin('p.Tags t')
            ->where('t.tag = ?', $tag_name);
            ;
        if (!$us->hasCredential('posts.view_hidden') || $filter===TRUE) {
            $query->andWhere('p.is_published = ?', true);
        }
        
        return $query->execute();
	}
	
	/**
	 * Retrieve single blog post using post shortcut and date or post id
	 *  
	 * @param integer $post_id
	 * @param mixed $shortcut string or null
	 * @param mixed $date DateTime or null
	 * @return Post Return false if there is no such post
	 */
	public function getPost($post_id, $shortcut=null, $date=null)
	{
	    if (!is_null($post_id)) {
            return Doctrine::getTable('Post')->find($post_id);
	    }
	    
	    if (is_null($shortcut)) {
	        return FALSE;
	    }
	    
        $query = Doctrine_Query::create()
            ->from('Post p')
            ->where('p.shortcut = ?', $shortcut)
            ;
        if ($date instanceof DateTime) {
            $dt = clone $date;
            $dt->setTime(0, 0, 0);
            $ndt = clone $dt;
            $ndt->modify('+1 day');
            $query->andWhere('p.post_time >= ? and p.post_time < ?', array($dt->format('Y-m-s'), $ndt->format('Y-m-d')));
        }
        //var_dump($query->getSqlQuery(), $ndt->format('Y-m-d'));
        $result = $query->execute();
        return $result->getFirst();
	}
	
	/**
	 * Delete post with given id
	 *
	 * @param integer $post_id
	 * @throws Doctrine_Exception
	 */
	public function deletePost($post_id)
	{
	    $post = $this->getPost($post_id);
	    $con = $this->getPDO();
	    
	    $con->beginTransaction();
	    try {
	        $post->delete($con);
	        $con->commit();
	    } catch (Doctrine_Exception $e) {
	        $con->rollback();
	        throw $e;
	    }
	}
	
	/**
	 * Find tags, use $t->getString('count') to get number of tag occurences.
	 *
	 * @return array Array of pairs (tag, cnt), where `tag' is a tag name,
	 * 		and `cnt' is number of occurences.
	 */
	public function findTags()
	{
        $query = Doctrine_Query::create()
            ->select('t.tag, COUNT(t.id) cnt')
            ->from('Tag t')
            ->groupBy('t.tag')
            ;
        $result = $query->execute();
        $rows = array();

        foreach ($result as $r) {
            if (!$r->tag) {
                continue;
            }
            $rows[] = array($r->tag, $r->cnt);
        }
        $result->free();
        return $rows;
	}
	
	/**
	 * Update post in the database.
	 *
	 * @param int $post_id
	 * @param DateTime $date
	 * @param string $subject
	 * @param string $body
	 * @param array $tags
	 * @param boolean $comments_allowed
	 * @param boolean $published
	 */
	public function updateBlogPost($post_id, $subject, $body, $tags, $comments_allowed, $published)
	{
	    $post = $this->getPost($post_id);
        if (!$post instanceof Post) {
            throw new PostNotFoundException();
        }
        
        $con = $this->getPdo();
        $con->beginTransaction();
        try {
            // set tags: delete old ones and set new
            foreach ($post->Tags as $t) {
                $t->delete($con);
            }
            
            // first remove duplicates from tags
            $new_tags = array();
            foreach ($tags as $t) {
                $new_tags[$t] = 1;
            }
            
            foreach (array_keys($new_tags) as $t) {
                $tag = new Tag();
                $tag->tag = $t;
                $tag->save($con);
                $post->Tags->add($tag);
            }
            
            $post->is_commenting_enabled = $comments_allowed;
            $post->is_published = $published;
            $post->title = $subject;
            $post->mod_time = date_create()->format('Y-m-d H:i:s');
            $post->Body->body = $body;
            $post->save($con);
            $con->commit();
            
        } catch (Doctrine_Exception $e) {
            $con->rollBack();
            throw $e;
        }
	}
	
	/**
	 * Create bew blog post.
	 *
	 * @param string $subject
	 * @param string $shortcut
	 * @param DateTime $date
	 * @param string $body
	 * @param array $tags
	 * @param boolean $comments_allowed
	 * @param boolean $published
	 * @return Post Just created Post instance
	 * @throws Doctrine_Exception
	 */
	public function addPost($subject, $shortcut, DateTime $date, $body, $tags, $comments_allowed, $published)
	{
	    $con = $this->getPdo();
	    $con->beginTransaction();
	    
	    $post = null;
	    try {
            $post_body = new PostBody();
            $post_body->body = $body;
            
	        $post = new Post();
            
	        // first remove duplicates from tags
            $new_tags = array();
            foreach ($tags as $t) {
                $new_tags[$t] = 1;
            }
            
            // add tags
            foreach (array_keys($new_tags) as $t) {
                $tag = new Tag();
                $tag->tag = $t;
                $tag->save($con);
                $post->Tags->add($tag);
            }
            
            $post->Body = $post_body;
            $post->shortcut = $shortcut;
            $post->title = $subject;
	        $post->post_time = $date->format('Y-m-d H:i:s');
	        $post->mod_time = $post->post_time;
            $post->is_commenting_enabled = $comments_allowed;
            $post->is_published = $published;
	        
	        $post->save();
	        $con->commit();
	    } catch (Doctrine_Exception $e) {
	        $con->rollback();
	        throw $e;
	    }
	    return $post;
	}
	
	/**
	 * Clear posts cache
	 *
	 * @param Post $post
	 * @param $flags
	 */
	public function clearPostCache(Post $post, $flags=array())
	{
	    if (is_array($flags) && isset($flags['clear_lists'])) {
	        AgaviExecutionFilter::clearCache(array('posts_list'));
	    }
	    $post_coordinates = $this->getPostCoordinates($post);
	    $post_cache_path = array('posts');
        foreach (array('year', 'month', 'day', 'shortcut') as $cc) {
            $post_cache_path[] = $post_coordinates[$cc];
        }
        AgaviExecutionFilter::clearCache($post_cache_path);
	}
}

?>
